package pub.tbc.api.handler;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;
import pub.tbc.api.config.ProjectConfig;
import pub.tbc.toolkit.core.EmptyUtil;

import java.net.InetSocketAddress;

import static io.netty.handler.codec.http.HttpUtil.setContentLength;

/**
 * 心跳检测(被检测)处理器，拦截心跳检测请求，并做出响应；<br>
 * 可配置心跳处理器的uri、响应内容;<br>
 * 默认uri为/heartbeat，默认响应内容为空；
 *
 * @author tbc on 2017/3/24 17:01:14.
 */
@Slf4j
public class HeartbeatHandler extends AbstractHttpInboundHandler {
    private ProjectConfig projectConfig = ProjectConfig.instance();
    /**
     * 默认的拦截路径
     */
    private String DEFAULT_URI = "/heartbeat";

    private String getIpv4(String ip) {
        if (ip.indexOf(".") > 0) return ip;
        if (ip.contains(":")) {
            log.debug("将IPv6转换来IPv4");
            int index = ip.lastIndexOf(":") + 1;
            String lastV6 = ip.substring(index);

        }
        return null;
    }

    private String getRemoteIp(ChannelHandlerContext context, FullHttpRequest request) {
        String clientIP = request.headers().get("X-Forwarded-For");
        if (clientIP == null) {
            InetSocketAddress inSocket = (InetSocketAddress) context.channel().remoteAddress();
            clientIP = inSocket.getAddress().getHostAddress();
        }
        return clientIP;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext context, FullHttpRequest request) throws Exception {
        String heartbeatUri = projectConfig.heartbeatUri();
        if (EmptyUtil.isEmpty(heartbeatUri)) {
            heartbeatUri = DEFAULT_URI;
        }
        if (heartbeatUri.equalsIgnoreCase(request.uri())) {
            log.info("receive the heartbeat request from {} ", getRemoteIp(context, request));
            FullHttpResponse response;
            String resMsg = projectConfig.heartbeatResMsg();
            if (EmptyUtil.isEmpty(resMsg)) {
                response = new DefaultFullHttpResponse(
                        HttpVersion.HTTP_1_1,
                        HttpResponseStatus.OK
                );
                setContentLength(response, 0);
            } else {
                byte[] bytes = resMsg.getBytes();
                response = new DefaultFullHttpResponse(
                        HttpVersion.HTTP_1_1,
                        HttpResponseStatus.OK,
                        Unpooled.wrappedBuffer(bytes)
                );
                setContentLength(response, bytes.length);
            }
            ChannelFuture future = context.writeAndFlush(response);
            if (!HttpUtil.isKeepAlive(request)) {
                future.addListener(ChannelFutureListener.CLOSE);
            }
        } else
            context.fireChannelRead(request);
    }
}
